﻿// Copyrights (c) 2017 GlassGrass

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniRx;



namespace GlassGrass.Unity.GuiFramework
	{

	/// <summary> Begin binding method utility for GuiElement. </summary>
	internal static class GuiBindingFactory
		{

		/// <summary> Begin binding with monodirectional updation. </summary>
		/// <typeparam name="TValue"></typeparam>
		/// <typeparam name="TDisplay"></typeparam>
		/// <param name="modelObj"> [Non-Nullable] </param>
		/// <param name="modelProperty"></param>
		/// <param name="viewObj"> [Non-Nullable] </param>
		/// <param name="viewProperty"></param>
		/// <param name="converter"></param>
		/// <returns></returns>
		/// <exception cref="System.ArgumentNullException"></exception>
		/// <exception cref="System.ArgumentException">
		///     Type of modelObj does not have modelProperty property.
		///       or
		///     Type of viewObj does not have viewProperty property.
		/// </exception>
		internal static Binding<TValue, TDisplay> BeginBinding<TValue, TDisplay>(
			object              modelObj, string modelProperty,
			IBindable<TDisplay> viewObj , string viewProperty,
			IValueConverter<TValue, TDisplay> converter)
			=> new Binding<TValue, TDisplay>( modelObj, modelProperty, viewObj, viewProperty, converter );



		/// <summary> Begin binding with bidirectional updation. </summary>
		/// <typeparam name="TValue"></typeparam>
		/// <typeparam name="TDisplay"></typeparam>
		/// <param name="modelObj"> [Non-Nullable] </param>
		/// <param name="modelProperty"></param>
		/// <param name="viewObj"> [Non-Nullable] </param>
		/// <param name="viewProperty"></param>
		/// <param name="updater"> [Non-Nullable] </param>
		/// <param name="converter"></param>
		/// <returns></returns>
		/// <exception cref="System.ArgumentNullException"></exception>
		/// <exception cref="System.ArgumentException">
		///     Type of modelObj does not have modelProperty property.
		///       or
		///     Type of viewObj does not have viewProperty property.
		/// </exception>
		internal static Binding<TValue, TDisplay> BeginBinding<TValue, TDisplay>(
			object              modelObj, string modelProperty,
			IBindable<TDisplay> viewObj , string viewProperty,
			IValueConverter<TValue, TDisplay> converter,
			IObservable<TDisplay> updater)
			{
			if(updater==null)
				throw new ArgumentNullException(nameof(updater));

			var binding = new Binding<TValue, TDisplay>( modelObj, modelProperty, viewObj, viewProperty, converter );
			var deregistrator = updater.Subscribe( _ => binding.UpdateModelByView() );
			binding.Disposed.Subscribe( _ => deregistrator.Dispose() );
			return binding;
			}

		}
	}
